package it.crosato.stage.shared.objects;

import java.util.Vector;

public class Reaction {
	
	private enum Type {REVERSIBLE, IRREVERSIBLE};
	
	private String id;
	private Type type;
	private Vector<ReactionElement> substrates = new Vector<ReactionElement>();
	private Vector<ReactionElement> products = new Vector<ReactionElement>();
	private Vector<String> enzymes;
	
	public Reaction() {
		
	}
	
	public Reaction(String id, boolean reversible, Vector<ReactionElement> substrates,
			Vector<ReactionElement> products, Vector<String> enzymes) {
		this.id = id;
		if (reversible) {
			this.type = Type.REVERSIBLE;
		}
		else {
			this.type = Type.IRREVERSIBLE;
		}
		this.substrates = substrates;
		this.products = products;
		this.enzymes = enzymes;
	}
	
	/**
	 * Costruisce una reazione chimica a partire dalla sua equazione.
	 * @param id il codice della reazione
	 * @param equation l'equazione chimica
	 * @param enzymes la lista degli enzimi che catalizzano la reazione
	 */
	public Reaction(String id, String equation, Vector<String> enzymes) {
		this.id = id;
		setEquation(equation);
		this.enzymes = enzymes;
	}
	
	/**
	 * Se la reazione è reversibile ne costruisce l'inversa e la ritorna
	 * @return la reazione inversa
	 */
	public Reaction getReverse() {
		if (isReversible()) {
			return new Reaction (id + "r", true, products,
					substrates, enzymes);
		}
		else {
			return null;
		}
	}
	
	/**
	 * Costruisce l'equazione della reazione e la restituisce
	 * @return l'equazione chimica della reazione
	 */
	public String getEquation() {
		String equation = "";
		for (int i = 0; i < substrates.size(); i++) {
			String compound = substrates.get(i).getElementCode();
			int factor = substrates.get(i).getStoichiometricFactor();
			if (factor == 1) {
				equation += compound;
			}
			else {
				equation += factor + " " + compound;
			}
			if (i < substrates.size() - 1) {
				equation += " + ";
			}
		}
		if (isReversible()) {
			equation += " <=> ";
		}
		else {
			equation += " => ";
		}
		for (int i = 0; i < products.size(); i++) {
			String compound = products.get(i).getElementCode();
			int factor = products.get(i).getStoichiometricFactor();
			if (factor == 1) {
				equation += compound;
			}
			else {
				equation += factor + " " + compound;
			}
			if (i < products.size() - 1) {
				equation += " + ";
			}
		}
		return equation;
	}
	
	/**
	 * Setta gli attributi della reazione a seconda dell'equazione data in ingresso
	 * @param equation l'equazione che descrive la reazione
	 */
	public void setEquation(String equation) {
		equation = equation.trim();
		String[] members = new String[2];
		if (equation.contains("<=>")) {
			members = equation.split("<=>");
			type = Type.REVERSIBLE;
		}
		else {
			members = equation.split("=>");
			type = Type.IRREVERSIBLE;
		}
		String[] subs = members[0].split("\\s\\+\\s");
		String[] prod = members[1].split("\\s\\+\\s");
		for (int i = 0; i < subs.length; i++) {
			substrates.add(new ReactionElement(subs[i]));
		}
		for (int i = 0; i < prod.length; i++) {
			products.add(new ReactionElement(prod[i]));
		}
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public boolean isReversible() {
		return (type == Type.REVERSIBLE);
	}
	public void setReversible(boolean reversible) {
		if (reversible) {
			type = Type.REVERSIBLE;
		}
		else {
			type = Type.IRREVERSIBLE;
		}
	}
	
	// stabilisce se la reazione è l'inversa o la normale
	public boolean isReverse() {
		return (id.charAt(id.length() - 1) == 'r');
	}
	
	public Vector<ReactionElement> getSubstrates() {
		return substrates;
	}
	public void setSubstrates(Vector<ReactionElement> substrates) {
		this.substrates = substrates;
	}
	
	public Vector<ReactionElement> getProducts() {
		return products;
	}
	public void setProducts(Vector<ReactionElement> products) {
		this.products = products;
	}
	
	public Vector<String> getEnzymes() {
		return enzymes;
	}
	public void setEnzymes(Vector<String> enzymes) {
		this.enzymes = enzymes;
	}
}
